#include <gtk-3.0/gtk/gtk.h>
#include <string.h>
#include <stdlib.h>
#include "main_window_widget.h"
#include "track_box_widget.h"
#include "tux_gsettings.h"
#include "audio_device_dialog_widget.h"
#include "alsa_detect.h"
#include "pulseaudio_detect.h"
#include "jack_detect.h"
#include "track_data_widget.h"

typedef struct main_window_widget_private MainWindowWidgetPrivate;

static GArray *tracks_boxes_array = NULL;
gdouble track_location=-1;
gdouble marker_location=-1;
gboolean is_record_active=FALSE;

struct _main_window_widget 
{
    GtkWindow parent;
    MainWindowWidgetPrivate *priv;
    
};

struct _main_window_widget_class
{
    GtkWindowClass parent_class;
};

struct main_window_widget_private 
{
    GtkWidget *tracks_device_box, *tracks_edit_box, *top_time_drawingarea, *bottom_time_drawingarea;
    
};


G_DEFINE_TYPE_WITH_PRIVATE(MainWindowWidget,main_window_widget,GTK_TYPE_WINDOW);

enum {
    PROP_0,
};


static void main_window_widget_init(MainWindowWidget *widget) {
    widget->priv = G_TYPE_INSTANCE_GET_PRIVATE(widget, MAIN_WINDOW_WIDGET_TYPE, MainWindowWidgetPrivate);
    gtk_widget_init_template(GTK_WIDGET(widget));   
}


MainWindowWidget *main_window_widget_new(void) {
    tracks_boxes_array = g_array_new(TRUE, TRUE, sizeof(TrackBoxWidget *));
    return g_object_new(MAIN_WINDOW_WIDGET_TYPE,NULL);
}


static void
main_window_widget_set_property (GObject         *object,
                         guint            prop_id,
                         const GValue    *value,
                         GParamSpec      *pspec)
{
  MainWindowWidget *widget = MAIN_WINDOW_WIDGET (object);

  switch (prop_id)
    {
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
    }
}

static void
main_window_widget_get_property (GObject         *object,
                        guint            prop_id,
                        GValue          *value,
                        GParamSpec      *pspec)
{
  MainWindowWidget *widget = MAIN_WINDOW_WIDGET (object);

  switch (prop_id)
    {
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
    }
}

static void record_toolbutton_toggled_cb(MainWindowWidget *widget, GtkWidget *g_widget) {
    guint i;
    is_record_active=gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(g_widget));
    if (is_record_active) {
        for (i=0;i<tracks_boxes_array->len;i++) {
            TrackBoxWidget *track_widget = g_array_index(tracks_boxes_array,TrackBoxWidget *,i);
            prepare_for_recording(track_widget);
        }
    } else {
        for (i=0;i<tracks_boxes_array->len;i++) {
            TrackBoxWidget *track_widget = g_array_index(tracks_boxes_array,TrackBoxWidget *,i);
            stop_recording(track_widget);
        }
    }
}


static gboolean motion_top_time_track_notify_event_cb(MainWindowWidget *widget,
               GdkEvent  *event,
               GtkWidget *g_widget) {
    gdouble x_value;
    int i;
    if (!gdk_event_get_axis(event,GDK_AXIS_X,&x_value)) {
        g_critical("could not get axis for GdKEvent");
    }
    track_location=x_value;
    gtk_widget_queue_draw(widget->priv->top_time_drawingarea);
    gtk_widget_queue_draw(widget->priv->bottom_time_drawingarea);
    for (i=0;i<tracks_boxes_array->len;i++) {
        TrackBoxWidget *track_widget = g_array_index(tracks_boxes_array,TrackBoxWidget *,i);
        gtk_widget_queue_draw(GTK_WIDGET(get_track_data_widget_from_track_box_widget(track_widget)));
    }
    return FALSE;
}

static gboolean button_bottom_time_track_press_event_cb(MainWindowWidget *widget, GdkEvent *event, GtkWidget *g_widget) {
    gdouble x_value;
    guint button, i;
    if (!gdk_event_get_axis(event,GDK_AXIS_X,&x_value)) {
        g_critical("could not get axis from GdKEvent");
    }
    if (!gdk_event_get_button(event, &button)) {
        g_critical("could not get button from GdkEvent");
    }
    g_debug("button %d x: %.2f\n",button, x_value);
    if (button == 1) {
        marker_location=x_value;
        gtk_widget_queue_draw(widget->priv->top_time_drawingarea);
        gtk_widget_queue_draw(widget->priv->bottom_time_drawingarea);
    for (i=0;i<tracks_boxes_array->len;i++) {
        TrackBoxWidget *track_widget = g_array_index(tracks_boxes_array,TrackBoxWidget *,i);
        gtk_widget_queue_draw(GTK_WIDGET(get_track_data_widget_from_track_box_widget(track_widget)));
    }
    }
    return FALSE;
}

static gboolean top_time_enter_event_cb(GtkWidget *widget, GdkEvent *event, gpointer user_data) {
    return FALSE;
}

static gboolean bottom_time_enter_event_cb(GtkWidget *widget, GdkEvent *event, gpointer user_data) {
    return FALSE;
}

static gboolean top_time_leave_event_cb(MainWindowWidget *widget, GdkEvent *event, GtkWidget *g_widget) {
    guint i;
    track_location=-1;
    gtk_widget_queue_draw(widget->priv->top_time_drawingarea);
    gtk_widget_queue_draw(widget->priv->bottom_time_drawingarea);
    for (i=0;i<tracks_boxes_array->len;i++) {
        TrackBoxWidget *track_widget = g_array_index(tracks_boxes_array,TrackBoxWidget *,i);
        gtk_widget_queue_draw(GTK_WIDGET(get_track_data_widget_from_track_box_widget(track_widget)));
    }
    return FALSE;
}

static gboolean bottom_time_leave_event_cb(MainWindowWidget *widget, GdkEvent *event, GtkWidget *g_widget) {
    guint i;
    track_location=-1;
    gtk_widget_queue_draw(widget->priv->top_time_drawingarea);
    gtk_widget_queue_draw(widget->priv->bottom_time_drawingarea);
    for (i=0;i<tracks_boxes_array->len;i++) {
        TrackBoxWidget *track_widget = g_array_index(tracks_boxes_array,TrackBoxWidget *,i);
        gtk_widget_queue_draw(GTK_WIDGET(get_track_data_widget_from_track_box_widget(track_widget)));
    }
    return FALSE;
}


static gboolean button_top_time_track_press_event_cb(MainWindowWidget *widget, GdkEvent *event, GtkWidget *g_widget) {
    return button_bottom_time_track_press_event_cb(widget, event, g_widget);
}

static gboolean motion_bottom_time_track_notify_event_cb(MainWindowWidget *widget,
               GdkEvent  *event,
               GtkWidget *g_widget) {
    return motion_top_time_track_notify_event_cb(widget, event, g_widget);
}

static void draw_time_handler(GtkWidget *widget, cairo_t *cr,gpointer data) {
  guint width = gtk_widget_get_allocated_width (widget);
  guint height = gtk_widget_get_allocated_height (widget);
  guint i=0;
  double center = height/2;
    cairo_set_source_rgb(cr, 0, 0, 0);
    cairo_set_line_width(cr, 0.5);
  while (i*3<=width) {
      guint line_size=2;
      if ((i+1) % 10 == 0) {
          line_size=5;
      }
  cairo_move_to(cr, i*3, center-line_size);
  cairo_line_to(cr, i*3, center+line_size);
  i++;
  }
    if (marker_location>=0) {
        cairo_move_to(cr,marker_location,0);
        cairo_line_to(cr,marker_location,height);
    }
    if (track_location>=0) {
        cairo_move_to(cr,track_location,0);
        cairo_line_to(cr,track_location,height);          
    }
 
    cairo_stroke(cr);
  
    
}

static void tracks_deck_add_new_track(MainWindowWidget *main_window,GtkWidget *widget) {
    GVariant *audio_devices_in = tux_gsettings_audio_devices_in_load();
    TrackDataWidget *track_data_fixed_widget =track_data_widget_new();
    gtk_container_add(GTK_CONTAINER(main_window->priv->tracks_edit_box),GTK_WIDGET(track_data_fixed_widget));
    TrackBoxWidget *track_box_widget = track_box_widget_new(GTK_WIDGET(track_data_fixed_widget),audio_devices_in);
    gtk_container_add(GTK_CONTAINER(main_window->priv->tracks_device_box),GTK_WIDGET(track_box_widget));
    g_array_append_val(tracks_boxes_array,track_box_widget);
    
}

static void audio_in_dialog_show(MainWindowWidget *main_window,GtkWidget *widget) {
    audio_device_item **devices=malloc(sizeof(audio_device_item *)*MAX_AUDIO_DEVICES);
    alsa_device *alsa_devices = create_alsa_array(MAX_AUDIO_DEVICES);
    gsize device_count;
    guint8 i;
    gsize devices_count;
    devices_count=0;
    
    alsa_get_capture_device_list(alsa_devices,&device_count);
    for (i=0;i<device_count;i++) {
        char *device_name=alsa_get_hardware_string_allocated(alsa_devices,i);
        char *device_desc = alsa_get_hardware_desc_alocated(alsa_devices,i);
        gboolean is_available = alsa_get_hardware_is_available(alsa_devices,i);
        
        
        devices[devices_count] = malloc(sizeof(audio_device_item));
        devices[devices_count]->server_name = malloc(5);
        sprintf(devices[devices_count]->server_name,"alsa");
        devices[devices_count]->device_name=device_name;
        devices[devices_count]->device_desc=device_desc;
        devices[devices_count]->is_available=is_available;
        devices_count++;
    }
    free(alsa_devices);
    if (is_pulseaudio_record_available()) {
        devices[devices_count] = malloc(sizeof(audio_device_item));
        devices[devices_count]->server_name = malloc(11);
        sprintf(devices[devices_count]->server_name,"pulse");
        devices[devices_count]->device_name=malloc(11);
        sprintf(devices[devices_count]->device_name,"pulseaudio");
        devices[devices_count]->device_desc=malloc(2);
        sprintf(devices[devices_count]->device_desc,"");
        devices[devices_count]->is_available=TRUE;
        devices_count++;
    }
    
    const char **ports = jack_get_input_devices();
    if (ports != NULL) {
        i=0;
        while (ports[i] != NULL) {
            size_t port_desc_len = strlen(ports[i])+1;
            devices[devices_count] = malloc(sizeof(audio_device_item));
            devices[devices_count]->server_name = malloc(5);
            sprintf(devices[devices_count]->server_name,"jack");
            devices[devices_count]->device_name=malloc(port_desc_len);
            memcpy(devices[devices_count]->device_name,ports[i],port_desc_len);
            devices[devices_count]->device_desc=malloc(2);
            sprintf(devices[devices_count]->device_desc,"");
            devices[devices_count]->is_available=TRUE;
            devices_count++;
            i++;
        }
        jack_free_ports_array(ports);
    }
    devices[devices_count]=NULL;
    AudioDeviceDialogWidget *audio_dialog = audio_device_dialog_widget_new(devices);
    audio_device_item_free(devices);
    gint response = gtk_dialog_run(GTK_DIALOG(audio_dialog));
    g_print("dialog response %d\n",response);
switch (response)
  {
    case GTK_RESPONSE_ACCEPT:
        g_print("Accept\n");
       break;
    default:
        g_print("Decline\n");
       break;
  }
gtk_widget_destroy (GTK_WIDGET(audio_dialog));
}


static void main_window_widget_class_init(MainWindowWidgetClass *class) {
    GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(class);
    GObjectClass *gobject_class = G_OBJECT_CLASS(class);
    
    gobject_class->set_property=main_window_widget_set_property;
    gobject_class->get_property=main_window_widget_get_property;
  
    gtk_widget_class_set_template_from_resource (widget_class,
                                               "/com/tuxin/tuxmusicstudio/main_window.glade");
  
 gtk_widget_class_bind_template_child_private(widget_class, MainWindowWidget, tracks_device_box);
 gtk_widget_class_bind_template_child_private(widget_class, MainWindowWidget, tracks_edit_box);
 gtk_widget_class_bind_template_child_private(widget_class, MainWindowWidget, top_time_drawingarea);
 gtk_widget_class_bind_template_child_private(widget_class, MainWindowWidget, bottom_time_drawingarea);
 
 gtk_widget_class_bind_template_callback(widget_class, draw_time_handler);
 gtk_widget_class_bind_template_callback(widget_class, tracks_deck_add_new_track);
 gtk_widget_class_bind_template_callback(widget_class, audio_in_dialog_show);
 gtk_widget_class_bind_template_callback(widget_class, motion_top_time_track_notify_event_cb);
 gtk_widget_class_bind_template_callback(widget_class, motion_bottom_time_track_notify_event_cb);
 gtk_widget_class_bind_template_callback(widget_class, button_bottom_time_track_press_event_cb);
 gtk_widget_class_bind_template_callback(widget_class, button_top_time_track_press_event_cb);
 gtk_widget_class_bind_template_callback(widget_class, top_time_enter_event_cb);
 gtk_widget_class_bind_template_callback(widget_class, bottom_time_enter_event_cb);
 gtk_widget_class_bind_template_callback(widget_class, top_time_leave_event_cb);
 gtk_widget_class_bind_template_callback(widget_class, bottom_time_leave_event_cb);
 gtk_widget_class_bind_template_callback(widget_class, record_toolbutton_toggled_cb);
}

